/*
 * @Author: Joel
 * @Date: 2025-04-17 14:18:38
 * @LastEditors: Joel
 * @LastEditTime: 2025-04-17 16:15:40
 * @FilePath: /gd32f303cct6/usr/board_driver/ems_ctrl.c
 * @Description: 
 * Copyright (C) 2025 YiJiaLink, All Rights Reserved. 
 * 2025-04-17 14:18:38
 */
#include"ems_ctrl.h"

static void gpio_config(void);
static void timer_config(void);
static void ems_pwm_init(void);
static void stop_pwm(enum EMS_PWM EMS_CHANNEL,uint8_t flag);
static void set_pwm(enum EMS_PWM EMS_CHANNEL,uint32_t duty);
static struct ems_func ems_pwm;
/*!
    \brief      configure the GPIO ports
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void gpio_config(void)
{
    rcu_periph_clock_enable(EMS_GPIO_CLK);
    rcu_periph_clock_enable(RCU_AF);

    /*Configure PB6 PB7 PB8(TIMER3 CH0 CH1 CH2) as alternate function*/
    gpio_init(EMS_GPIO_PORT,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,EMS_PWM1_PIN);
    gpio_init(EMS_GPIO_PORT,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,EMS_PWM2_PIN);
    gpio_init(EMS_GPIO_PORT,GPIO_MODE_AF_PP,GPIO_OSPEED_50MHZ,EMS_PWM_BOOT_PIN);
}

/*!
    \brief      configure the TIMER peripheral
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void timer_config(void)
{
    /* -----------------------------------------------------------------------
    TIMER3 configuration: generate 3 PWM signals with 3 different duty cycles:
    TIMER3CLK = SystemCoreClock / 120 = 1MHz

    TIMER3 channel0 duty cycle = (4000/ 16000)* 100  = 25%
    TIMER3 channel1 duty cycle = (8000/ 16000)* 100  = 50%
    TIMER3 channel2 duty cycle = (12000/ 16000)* 100 = 75%
    ----------------------------------------------------------------------- */
    timer_oc_parameter_struct timer_ocintpara;
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER3);

    timer_deinit(TIMER3);

    /* TIMER3 configuration */
    timer_initpara.prescaler         = 2;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 1599;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER3,&timer_initpara);

    /* CH0,CH1 and CH2 configuration in PWM mode */
    timer_ocintpara.outputstate  = TIMER_CCX_ENABLE;
    timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
    timer_ocintpara.ocpolarity   = TIMER_OC_POLARITY_HIGH;
    timer_ocintpara.ocnpolarity  = TIMER_OCN_POLARITY_HIGH;
    timer_ocintpara.ocidlestate  = TIMER_OC_IDLE_STATE_LOW;
    timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;

    timer_channel_output_config(TIMER3,TIMER_CH_0,&timer_ocintpara);
    timer_channel_output_config(TIMER3,TIMER_CH_1,&timer_ocintpara);
    timer_channel_output_config(TIMER3,TIMER_CH_2,&timer_ocintpara);

    /* CH0 configuration in PWM mode0,duty cycle 25% */
    timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_0,399);
    timer_channel_output_mode_config(TIMER3,TIMER_CH_0,TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3,TIMER_CH_0,TIMER_OC_SHADOW_DISABLE);

    /* CH1 configuration in PWM mode0,duty cycle 50% */
    timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_1,799);
    timer_channel_output_mode_config(TIMER3,TIMER_CH_1,TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3,TIMER_CH_1,TIMER_OC_SHADOW_DISABLE);

    /* CH2 configuration in PWM mode0,duty cycle 75% */
    timer_channel_output_pulse_value_config(TIMER3,TIMER_CH_2,1199);
    timer_channel_output_mode_config(TIMER3,TIMER_CH_2,TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3,TIMER_CH_2,TIMER_OC_SHADOW_DISABLE);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER3);
    /* auto-reload preload enable */
    timer_enable(TIMER3);
}
static void ems_pwm_init(void)
{
    gpio_config();
    timer_config();
    return;
}
static void stop_pwm(enum EMS_PWM EMS_CHANNEL,uint8_t flag)
{
   
    uint16_t select_channel;
    switch(EMS_CHANNEL)
    {
        case EMS_PWM1:
        select_channel = TIMER_CH_2;
        break;
        case EMS_PWM2:
        select_channel = TIMER_CH_1;
        break;
        case EMS_PWM_BOOT:
        select_channel = TIMER_CH_0;
        break;
    }
    timer_channel_output_pulse_value_config(TIMER3,select_channel,0);
    timer_channel_output_state_config(TIMER3,select_channel,TIMER_CCX_DISABLE);
    return;
}
static void set_pwm(enum EMS_PWM EMS_CHANNEL,uint32_t duty)
{
    uint16_t select_channel;
    switch(EMS_CHANNEL)
    {
        case   EMS_PWM1:
        select_channel = TIMER_CH_2;
        break;
        case EMS_PWM2:
        select_channel = TIMER_CH_1;
        break;
        case EMS_PWM_BOOT:
        select_channel = TIMER_CH_0;
        break;
    }
    timer_channel_output_pulse_value_config(TIMER3,select_channel,duty);
    return;
}
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
struct ems_func *ems_driver_init(void)
{
    struct ems_func *ems_func = &ems_pwm;
    ems_func->init_ems = ems_pwm_init;
    ems_func->run_ems = set_pwm;
    ems_func->stop_pump = stop_pwm;
    return ems_func;
}